<?php

namespace App\Jobs;

use App\Http\Controllers\Chanjet\TplusCommonController;
use App\Models\Custom\Custom;
use App\Models\Settle\SettleType;
use App\Services\Chanjet\ChanjetRequest;
use App\Services\Chanjet\LogFormatRecord;
use App\Services\Common\Common;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class ReceiptPayment implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $data;
    public $tries = 3;      // Laravel 自动重试次数（包括首次执行）
    public $timeout = 60;

    public function __construct($data)
    {
        $this->data = $data;
    }

    public function handle()
    {
        $data = $this->data;
        try {
            // 参数校验
            if (!isset($data["mangerinfo"], $data["api"], $data["param"])) {
                throw new \InvalidArgumentException("缺少必要参数: mangerinfo/api/param");
            }

            // 检查是否允许请求
            if (!TplusCommonController::isAllowRequestTplus($data["mangerinfo"])) {
                throw new \InvalidArgumentException("Chanjet API 请求被禁止");
            }
            $param = $this->getRequestParam();
            Log::info('收付款单'.json_encode($param));
            // 执行 API 请求
            $api = $data["api"];

            $res = ChanjetRequest::getInstance()->$api($param, $data["mangerinfo"]['org_id']);

            // 处理不同 API 的响应
            $this->validateApiResponse($api, $res);

            Log::info("Chanjet {$api}请求成功", ['data' => $data]);
        } catch (\Throwable $e) {
            $this->handleFailure($e);
        }
    }
    public function getRequestParam(){
        //创建账号
        $BankAccountName = $this->bankAccount();
        //创建结算方式  固定 网银
        $SettleStyleCode = $this->getSettleStyle();

        //付款单
        if($this->data["param"]["type"] == "purchase"){
            $info = $this->data["param"]["info"];
            $Chanjet_param = [
                "dto" => [
                    "VoucherDate" => date('Y-m-d'),
                    "Code" => $info['pay_sn_code'].'|'.$this->data["param"]["PurchasePayOrderApproveSubId"],//付款单单据编号 +sub单据id
                    "IsModifiedCode" => "true",
                    "ExternalCode" => $info['pay_sn_code'].'|'.$this->data["param"]["PurchasePayOrderApproveSubId"],
                    "Partner" => [
                        "Code" => Custom::where('id',$info["custom_id"])->value("company_code"),
                    ],
                    //往来单位编码
                    "Department" => ["Code" => strval($this->data["mangerinfo"]["sys_dpm_id"])],//部门
                    "IsReceiveFlag" => "false",//赋值为true，则为收款单;赋值为false，则为付款单
                    "BusiType" => ["Code"=>"36"],//付款单时，包括35（普通付款），36（预付款）和46（直接付款）；
                    "ArapMultiSettleDetails" => [ //多结算明细
                        [
                            "SettleStyle" => ["code" => $SettleStyleCode],//网银code
                            "BankAccount" => ["name" => $BankAccountName],
                            "OrigAmount" => strval($this->data["param"]["req_data"]['pay_money']/100),
                        ]
                    ]
                ]
            ];
        }
        //收款单
        if($this->data["param"]["type"] == "receivemoney"){
            $ChanjetData = $this->data["param"]["ChanjetData"];
            $Chanjet_param = [
                "dto" => [
                    "VoucherDate" => date('Y-m-d', $ChanjetData['date']),
                    "Code" => $ChanjetData['code'],
                    "IsModifiedCode" => "true",
                    "ExternalCode" => $ChanjetData['code'],
                    "Partner" => ["Code" => $this->data["param"]["custom"]["company_code"]], //往来单位编码
                    "Department" => ["Code" => $this->data["mangerinfo"]['sys_dpm_id']],//部门
                    "IsReceiveFlag" => "true", //赋值为true，则为收款单;赋值为false，则为付款单
                    "BusiType" => ["Code" => "34"], //收款单时，包括33（普通收款），34（预收款）和45（直接收款）；
                    "ArapMultiSettleDetails" => [ //多结算明细 结算方式取网银
                        [
                            "SettleStyle" => ["code" => SettleType::where('id', $this->data["param"]["receivemoney"]["settlement_category_id"])->value("type_no")], //网银code 认款单
//                        "SettleStyle" => ["code" => SettleType::where('id', $receivemoney["settlement_category"])->value("type_no")], //网银code 认款单
                            "BankAccount" => ["name" => $BankAccountName],
                            "OrigAmount" => $ChanjetData['amount'] / 100,
                        ]
                    ]
                ]
            ];
        }
        //负数收款单，退款
        if($this->data["param"]["type"] == "refund"){
            $Chanjet_param = [
                "dto" => [
                    "VoucherDate" => date('Y-m-d',$this->data["param"]["data"]["create_at"]),
                    "Code" => $this->data["param"]["data"]["code"],
                    "IsModifiedCode" => "true",
                    "ExternalCode" => $this->data["param"]["data"]["code"],
                    "Partner" => [
                        "Code" => $this->data["param"]["custom"]["id"],
                        "Name" => $this->data["mangerinfo"]['realname'] . '_' . $this->data["param"]["custom"]['company_name'] . '_' . $this->data["param"]["custom"]['settlement_company'],
                    ],//往来单位编码
                    "Department" => ["Code" => strval($this->data["mangerinfo"]["sys_dpm_id"])],//部门
                    "IsReceiveFlag" => "true",//赋值为true，则为收款单;赋值为false，则为付款单
                    "BusiType" => ["Code"=>"34"],//收款单时，包括33（普通收款），34（预收款）和45（直接收款）；
                    "ArapMultiSettleDetails" => [ //多结算明细
                        [
                            "SettleStyle" => [SettleType::where('id', $this->data["param"]["data"]["settlement_category"])->value("type_no")], //网银code 认款单
                            "BankAccount" => ["name" => $BankAccountName],
                            "OrigAmount" => strval(-1 * abs($this->data["param"]["req_data"]['bk_amount']/100)),
                        ]
                    ]
                ]
            ];
        }
        return $Chanjet_param;
    }
    protected function validateApiResponse(string $api, $response)
    {
        switch ($api) {
            case "ReceivePaymentVoucherOpenApiNewCreate":
                if (isset($response['code']) && $response['code'] != '0') {
                    throw new \RuntimeException("Chanjet {$api} 请求失败");
                }
                break;
            case "BankAccountCreate":
                if (isset($response['code'])) {
                    throw new \RuntimeException("Chanjet {$api} 请求失败");
                }
                break;
            case "BankAccountCallBack":
                if (isset($response['code'])) {
                    throw new \RuntimeException("Chanjet {$api} 请求失败");
                }
                break;
        }
    }

    protected function handleFailure(\Throwable $e)
    {
        // 参数错误立即失败，不重试
        if ($e instanceof \InvalidArgumentException) {
            $this->failed($e);
            return;
        }

        // 可重试错误：达到最大尝试次数后标记失败
        if ($e instanceof \RuntimeException) {
            if ($this->attempts() >= $this->tries) {
                $this->failed($e);
            }else{
                throw $e;
            }
        }
    }

    public function failed(\Throwable $exception)
    {
        // 静默记录日志（非 error 级别）
        if($this->data["param"]["type"] == "purchase"){
            $message = "Chanjet 付款单,同步失败";
        }
        if($this->data["param"]["type"] == "receivemoney"){
            $message = "Chanjet 收款单,同步失败";
        }
        if($this->data["param"]["type"] == "refund"){
            $message = "Chanjet 退款单(负数收款单),同步失败";
        }

        Log::info($exception->getMessage().'failed方法');
        $this->data["error"] = $exception->getMessage();
        $this->data["res"] = $message;
        LogFormatRecord::error($this->data);
        return;
    }

    public function bankAccount(){
        /**
         *  创建账号
         *  使用华坤系统的 结算公司+办款银行 拼音 作为 账号的code创建
         *
         **/

        if($this->data["param"]["type"] == "purchase"){
            $settleCompany = $this->data["param"]["info"]["pa_settle_company_name"];
            $bank_name = $this->data["param"]["req_data"]['bank_name'];

        }
        if($this->data["param"]["type"] == "receivemoney"){
            $settleCompany = $this->data["param"]["ChanjetData"]["settlement_company"];
            $bank_name = $this->data["param"]["ChanjetData"]["bank_name"];
        }
        if($this->data["param"]["type"] == "refund"){
            $settleCompany = $this->data["data"]["settlement_company"];
            $bank_name = $this->data["data"]["bank_name"];
        }
        $BankAccountName = $settleCompany.'_'.$bank_name;
        $BankAccountCode =  common::getPinyin($settleCompany).'_'.common::getPinyin($bank_name);
        $this->createBankAccount($BankAccountCode,$BankAccountName,$this->data["mangerinfo"]["org_id"]);
        return $BankAccountName;
    }

    /**
     *  创建账号信息
     *
     */
    public function createBankAccount($code = "",$name = "",$org_id = 0)
    {
        if(!empty($code) && !empty($name)){
            $res = ChanjetRequest::getInstance()->BankAccountQuery(["dto"=>["Name"=>$name]],$org_id);
            $is_exist_bank_account = false;
            //T+账号查询接口，是模糊查询，需要进一步确认 账号是否已创建
            if(!empty($res)){
                foreach ($res as $key => $item){
                    if(isset($item['Code']) && isset($item['Name'])){
                        if($item['Code'] == $code && $item['Name'] == $name){
                            $is_exist_bank_account = true;
                            break;
                        }
                    }
                }
            }
            if(!$is_exist_bank_account){
                $param = [
                    "dto" => [
                        "Code" => $code,
                        "Name" => $name,
//                    "BankNoType" => [
//                        "Name"=>"银行"
//                    ],
//                    "BankName"=> [
//                        "Name" => $data["bank"]
//                    ],
//                    "BankNo" => $data["bank_number"]
                    ]
                ];

                $res = ChanjetRequest::getInstance()->BankAccountCreate($param, $this->data["mangerinfo"]["org_id"]);
                $this->validateApiResponse("BankAccountCreate", $res);
            }
        }
    }
    //结算方式
    public function getSettleStyle(){
        $is_exist_default = false;
        $res = ChanjetRequest::getInstance()->SettleStyleQuery(["dto"=>["Code"=>"wangyin"]],$this->data["mangerinfo"]["org_id"]);
        if($res){
            foreach($res as $item){
                if($item["Code"] == "wangyin"){
                    $is_exist_default = true;
                    break;
                }
            }
        }
        if(!$is_exist_default){
            //创建结算方式
            $Chanjet_param = [
                "param" => [
                    "Name" => "网银",
                    "Code" => "wangyin",
                    "BankAccountType" => "OTHER",
                ]
            ];
            $res = ChanjetRequest::getInstance()->BankAccountCallBack($Chanjet_param, $this->data["mangerinfo"]["org_id"]);
            $this->validateApiResponse("BankAccountCallBack", $res);
        }

        return "wangyin";//返回结算方式code
    }
}
